using System.Collections.Generic;
using UnityEngine;
using System;
using Cysharp.Threading.Tasks;
using System.Threading;

namespace ZYFramework.ObjectPool
{
    public partial class Com_ObjectPool<T> : IObjectPool<T>
    {

        /// <summary>
        /// 对象池配置
        /// </summary>
        private readonly ObjectPoolConfig<T> _config;

        private string _poolName;
        public string PoolName
        {
            get => _poolName;
            set => _poolName = value;
        }

        protected UnityEngine.GameObject _poolObjectRoot;

        /// <summary>
        /// 大容量池使用队列（按优先级）
        /// </summary>
        private readonly Queue<T> _poolQueues;
        /// <summary>
        /// 大对象池的缓存计数（避免每次访问Count时使用LINQ Sum）
        /// </summary>
        private int _cachedQueueCount = 0;

        /// <summary>
        /// 对象创建策略
        /// </summary>
        private readonly IObjectPolicy<T> _creationPolicy;

        /// <summary>
        /// 活跃对象集合
        /// </summary>
        private readonly HashSet<T> _activeObjects;

        #region 事件

        /// <summary>
        /// 对象创建事件
        /// </summary>
        public event Action<T> OnObjectCreated;

        /// <summary>
        /// 对象获取事件
        /// </summary>
        public event Action<T> OnObjectAcquired;

        /// <summary>
        /// 对象释放事件
        /// </summary>
        public event Action<T> OnObjectReleased;

        /// <summary>
        /// 对象销毁事件
        /// </summary>
        public event Action<T> OnObjectDestroyed;

        /// <summary>
        /// 池回收事件
        /// </summary>
        public event Action OnPoolRecycled;

        /// <summary>
        /// 池溢出事件
        /// </summary>
        public event Action OnPoolOverflow;

        #endregion

    }

    public partial class Com_ObjectPool<T>
    {

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config">配置</param>
        public Com_ObjectPool(ObjectPoolConfig<T> config, string poolName, GameObject poolRoot)
        {
            _poolObjectRoot = new UnityEngine.GameObject($"{poolName}");
            _poolObjectRoot.transform.SetParent(poolRoot.transform);

            _config = config ?? throw new ArgumentNullException(nameof(config));
            _poolName = poolName ?? throw new ArgumentNullException(nameof(config));
            _poolQueues = new Queue<T>(_config.MaxCapacity);
            _activeObjects = new HashSet<T>(_config.MaxCapacity);

            // 初始化策略
            _creationPolicy = new Com_ObjectPolicy<T>(
                config.CreationFunc_Sync,
                config.CreationFuncAsync,
                config.ActivationFunc_Sync,
                config.ActivationFunc_Async,
                config.DestroyFunc_Sync,
                config.DestroyFunc_Async,
                config.RecycleFunc_Sync,
                config.RecycleFunc_Async
                );

            if (_config.PrewarmCount > 0)
            {
                //预热一般不会被取消，所以这里直接new一个取消令牌
                PrewarmInternal_Async(new CancellationTokenSource().Token).Forget();
            }
        }

        /// <summary>
        /// 同步获取对象
        /// </summary>
        /// <param name="priority">优先级</param>
        /// <returns>池化对象</returns>
        public T Get_Sync()
        {
            return GetInternal_Sync();
        }

        /// <summary>
        /// 异步获取对象
        /// </summary>
        /// <param name="priority">优先级</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>池化对象</returns>
        public UniTask<T> Get_Async(CancellationToken cancellationToken = default)
        {
            return GetInternal_Async(cancellationToken);
        }

        /// <summary>
        /// 同步释放对象
        /// </summary>
        /// <param name="obj">要释放的对象</param>
        public void Release_Sync(object obj)
        {
            ReleaseInternal_Sync(obj);
        }

        /// <summary>
        /// 异步释放对象
        /// </summary>
        /// <param name="obj">要释放的对象</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask Release_Async(object obj, CancellationToken cancellationToken = default)
        {
            await ReleaseInternal_Async(obj, cancellationToken);
            await UniTask.CompletedTask;
        }

        #region 池管理

        /// <summary>
        /// 同步清理对象池
        /// </summary>
        public void Clear_Sync()
        {
            ClearInternal_Sync();
        }

        /// <summary>
        /// 异步清理对象池
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask Clear_Async(CancellationToken cancellationToken = default)
        {
            // Unity的GameObject操作必须在主线程，检查是否已在主线程，避免不必要的状态机分配
            if (!PlayerLoopHelper.IsMainThread)
            {
                await UniTask.SwitchToMainThread(cancellationToken);
            }

            await ClearInternal_Async(cancellationToken);
        }

        #endregion

        /// <summary>
        /// 检查对象是否在活跃对象池中
        /// </summary>
        /// <param name="obj">要检查的对象</param>
        /// <returns>是否在活跃对象池中</returns>
        public bool IsObjectInActivePool(object obj)
        {
            return _activeObjects.Contains((T)obj);
        }

        /// <summary>
        /// 检查对象是否在对象池中
        /// </summary>
        /// <param name="obj">要检查的对象</param>
        /// <returns>是否在对象池中</returns>
        public bool IsObjectInPool(object obj)
        {
            return _poolQueues.Contains((T)obj);
        }

        #region 预热

        /// <summary>
        /// 异步预热对象池
        /// </summary>
        private async UniTask PrewarmInternal_Async(CancellationToken cancellationToken = default)
        {
            for (int i = 0; i < _config.PrewarmCount; i++)
            {
                await GetPrewarmInternal_Async(cancellationToken);
            }
        }

        /// <summary>
        /// 内部异步获取对象实现
        /// </summary>
        /// <param name="priority">优先级</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>对象</returns>
        private async UniTask<T> GetPrewarmInternal_Async(CancellationToken cancellationToken = default)
        {
            T obj = default(T);

            // 如果池中没有对象，异步创建新对象
            if (obj == null)
            {
                obj = await _creationPolicy.Create_Async(cancellationToken);
            }

            // 检查容量限制
            //if (_cachedQueueCount >= _config.MaxCapacity)
            //{
            //await HandleOverflowAsync(obj, cancellationToken);
            //Debug.LogError($"ReleaseInternal_Async 对象池已满(这里要加临时溢出策略，暂时进行提示): {obj} -- {typeof(T).Name}");
            //return;
            //}

            // 添加到池中
            _poolQueues.Enqueue((T)obj);
            _cachedQueueCount++;

            // 获取 GameObject：支持 Component 和 GameObject 两种类型
            UnityEngine.GameObject gameObject = GetGameObject((T)obj);
            if (gameObject != null)
            {
                gameObject.transform.SetParent(_poolObjectRoot.transform);
            }

            return (T)obj;
        }

        #endregion

        #region 内部实现方法

        /// <summary>
        /// 获取 GameObject，支持 Component 和 GameObject 两种类型
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>GameObject，如果无法获取则返回 null</returns>
        private UnityEngine.GameObject GetGameObject(T obj)
        {
            if (obj == null) return null;

            // 如果是 Component 类型，通过 gameObject 属性获取
            if (obj is UnityEngine.Component component)
            {
                return component.gameObject;
            }

            // 如果是 GameObject 类型，直接返回
            if (obj is UnityEngine.GameObject gameObject)
            {
                return gameObject;
            }

            // 其他类型返回 null
            return null;
        }

        /// <summary>
        /// 内部获取对象实现
        /// </summary>
        /// <param name="priority">优先级</param>
        /// <returns>对象</returns>
        private T GetInternal_Sync()
        {
            T obj = default(T);

            // 大对象池逻辑
            if (_poolQueues.Count > 0)
            {
                obj = _poolQueues.Dequeue();
                _cachedQueueCount--;
            }

            // 如果池中没有对象，创建新对象
            if (obj == null)
            {
                obj = _creationPolicy.Create_Sync();
                OnObjectCreated?.Invoke(obj);
            }

            // 激活对象
            // 尝试激活对象，如果失败则清理
            try
            {
                _creationPolicy.Activate_Sync(obj);
            }
            catch
            {
                // 激活失败，销毁已创建的对象并回滚统计
                _creationPolicy.Destroy_Sync(obj);
                throw new Exception($"GetInternal 激活对象失败 -- 已销毁对象 -- {typeof(T).Name}"); // 重新抛出异常
            }

            // 更新状态
            _activeObjects.Add(obj);

            OnObjectAcquired?.Invoke(obj);

            return obj;
        }

        /// <summary>
        /// 内部异步获取对象实现
        /// </summary>
        /// <param name="priority">优先级</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>对象</returns>
        private async UniTask<T> GetInternal_Async(CancellationToken cancellationToken = default)
        {
            T obj = default(T);
            // 大对象池逻辑
            if (_poolQueues.Count > 0)
            {
                obj = _poolQueues.Dequeue();
                _cachedQueueCount--;
            }

            // 如果池中没有对象，异步创建新对象
            if (obj == null)
            {
                obj = await _creationPolicy.Create_Async(cancellationToken);
                OnObjectCreated?.Invoke(obj);
            }

            // 尝试激活对象，如果失败则清理
            try
            {
                await _creationPolicy.Activate_Async(obj, cancellationToken);
            }
            catch
            {
                // 激活失败，销毁已创建的对象并回滚统计
                await _creationPolicy.Destroy_Async(obj);
                throw new Exception($"GetInternalAsync 激活对象失败 -- 已销毁对象 -- {typeof(T).Name}"); // 重新抛出异常
            }

            // 更新状态
            _activeObjects.Add(obj);

            OnObjectAcquired?.Invoke(obj);

            return obj;
        }

        /// <summary>
        /// 内部释放对象实现
        /// </summary>
        /// <param name="obj">对象</param>
        private void ReleaseInternal_Sync(object obj)
        {
            if (!_activeObjects.Contains((T)obj))
            {
                Debug.Log($"ReleaseInternal_Sync 尝试释放非活跃对象: {obj}");
                return;
            }

            // 检查容量限制
            //if (_cachedQueueCount >= _config.MaxCapacity)
            //{
            //HandleOverflow(obj);
            //    Debug.LogError($"ReleaseInternal_Sync 对象池已满(这里要加临时溢出策略，暂时进行提示): {obj} -- {typeof(T).Name}");
            //return;
            //}

            // 回收对象
            _creationPolicy.Recycle_Sync((T)obj);

            // 更新状态
            _activeObjects.Remove((T)obj);

            // 添加到池中
            _poolQueues.Enqueue((T)obj);
            _cachedQueueCount++;

            // 获取 GameObject：支持 Component 和 GameObject 两种类型
            UnityEngine.GameObject gameObject = GetGameObject((T)obj);
            if (gameObject != null)
            {
                gameObject.transform.SetParent(_poolObjectRoot.transform);
            }

            OnObjectReleased?.Invoke((T)obj);
        }

        /// <summary>
        /// 内部异步释放对象实现
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="cancellationToken">取消令牌</param>
        private async UniTask ReleaseInternal_Async(object obj, CancellationToken cancellationToken)
        {
            if (!_activeObjects.Contains((T)obj))
            {
                Debug.Log($"ReleaseInternal_Async 尝试释放非活跃对象: {obj}");
                return;
            }

            // 检查容量限制
            //if (_cachedQueueCount >= _config.MaxCapacity)
            //{
            //await HandleOverflowAsync(obj, cancellationToken);
            //    Debug.LogError($"ReleaseInternal_Async 对象池已满(这里要加临时溢出策略，暂时进行提示): {obj} -- {typeof(T).Name}");
            //return;
            //}

            // 异步回收对象
            await _creationPolicy.Recycle_Async((T)obj, cancellationToken);

            // 更新状态
            _activeObjects.Remove((T)obj);

            // 添加到池中
            _poolQueues.Enqueue((T)obj);
            _cachedQueueCount++;

            // 获取 GameObject：支持 Component 和 GameObject 两种类型
            UnityEngine.GameObject gameObject = GetGameObject((T)obj);
            if (gameObject != null)
            {
                gameObject.transform.SetParent(_poolObjectRoot.transform);
            }

            OnObjectReleased?.Invoke((T)obj);
        }

        /// <summary>
        /// 内部清理实现
        /// </summary>
        private void ClearInternal_Sync()
        {
            // 销毁所有对象（优化：直接遍历，避免ToList()）
            var allObjects = new List<T>(_activeObjects);

            foreach (var obj in allObjects)
            {
                _creationPolicy.Destroy_Sync(obj);
                OnObjectDestroyed?.Invoke(obj);
            }

            // 清理数据结构
            _poolQueues.Clear();
            _cachedQueueCount = 0;

            _activeObjects.Clear();
        }

        /// <summary>
        /// 内部异步清理实现
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        private async UniTask ClearInternal_Async(CancellationToken cancellationToken)
        {
            // 销毁所有对象（优化：直接遍历，避免ToList()）
            var allObjects = new List<T>(_activeObjects);

            foreach (var obj in allObjects)
            {
                await _creationPolicy.Destroy_Async(obj, cancellationToken);
                OnObjectDestroyed?.Invoke(obj);
            }

            // 清理数据结构
            _poolQueues.Clear();
            _cachedQueueCount = 0;

            _activeObjects.Clear();
        }

        #endregion

        #region 批量操作

        /// <summary>
        /// 批量获取GameObject
        /// </summary>
        /// <param name="count">获取数量</param>
        /// <param name="priority">优先级</param>
        /// <returns>GameObject数组</returns>
        public T[] GetRange_Sync(int count)
        {
            var result = new T[count];

            for (int i = 0; i < count; i++)
            {
                result[i] = GetInternal_Sync();
            }

            return result;
        }

        /// <summary>
        /// 批量释放
        /// </summary>
        /// <param name="objects">要释放的集合</param>
        public void ReleaseRange_Sync(List<T> objects)
        {
            if (objects == null) return;

            foreach (var obj in objects)
            {
                ReleaseInternal_Sync(obj);
            }
        }

        /// <summary>
        /// 异步批量获取
        /// </summary>
        /// <param name="count">获取数量</param>
        /// <param name="priority">优先级</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>数组</returns>
        public async UniTask<T[]> GetRange_Async(int count, CancellationToken cancellationToken = default)
        {
            var result = new T[count];

            // Unity的操作必须在主线程，检查是否已在主线程，避免不必要的状态机分配
            if (!PlayerLoopHelper.IsMainThread)
            {
                await UniTask.SwitchToMainThread(cancellationToken);
            }

            int successCount = 0;
            try
            {
                for (int i = 0; i < count; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    result[i] = await GetInternal_Async(cancellationToken);
                    successCount++;
                }
            }
            catch
            {
                // 发生异常或取消时，清理已成功获取的对象
                // 使用finally确保资源清理，即使后续清理也失败
                for (int j = 0; j < successCount; j++)
                {
                    if (result[j] != null)
                    {
                        try
                        {
                            await ReleaseInternal_Async(result[j], cancellationToken);
                        }
                        catch
                        {
                            // 单个对象释放失败不影响其他对象的清理
                            // 继续清理其他对象，避免资源泄漏
                        }
                    }
                }
                throw new Exception($"GetRangeAsync 批量获取对象失败 -- {typeof(T).Name}");
            }

            return result;
        }

        /// <summary>
        /// 异步批量释放
        /// </summary>
        /// <param name="objects">要释放的对象集合</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async UniTask ReleaseRange_Async(List<T> objects, CancellationToken cancellationToken = default)
        {
            if (objects == null) return;

            // Unity的操作必须在主线程，检查是否已在主线程，避免不必要的状态机分配
            if (!PlayerLoopHelper.IsMainThread)
            {
                await UniTask.SwitchToMainThread(cancellationToken);
            }

            foreach (var obj in objects)
            {
                await ReleaseInternal_Async(obj, cancellationToken);
            }

        }

        #endregion

        #region 统计

        /// <summary>
        /// 获取活跃对象数量
        /// </summary>
        /// <returns>活跃对象数量</returns>
        public int GetActiveCount()
        {
            return _activeObjects.Count;
        }

        /// <summary>
        /// 获取空闲对象数量
        /// </summary>
        /// <returns>空闲对象数量</returns>
        public int GetIdleCount()
        {
            return _poolQueues.Count;
        }

        /// <summary>
        /// 获取总对象数量
        /// </summary>
        /// <returns>总对象数量</returns>
        public int GetTotalCount()
        {
            return _activeObjects.Count + _poolQueues.Count;
        }

        #endregion

    }


}